`timescale 1ns/1ps
module main_decoder (
    input       [6:0]   op,
    input       [2:0]   funct3,
    output  reg         reg_write,
    output  reg [2:0]   imm_src,
    output  reg [1:0]   alu_srcA,
    output  reg [1:0]   alu_srcB,
    output  reg         mem_write,
    output  reg [3:0]   mem_write_mask,
    output  reg         mem_en,
    output  reg [1:0]   result_src,
    output  reg         branch,
    output  reg [1:0]   alu_op,
    output  reg         jump
);

always @(*) begin
    case(op)
    7'b00000_11: begin    // lw
        reg_write       = 1'b1;
        imm_src         = 3'b000;
        alu_srcA        = 2'b10;
        alu_srcB        = 2'b01;
        mem_write       = 1'b0;
        mem_write_mask  = 4'b0000;
        mem_en          = 1'b1;
        result_src      = 2'b01;
        branch          = 1'b0;
        alu_op          = 2'b00;
        jump            = 1'b0;
    end
    7'b01000_11: begin    // sw,sh.sb
        reg_write       = 1'b0;
        imm_src         = 3'b001;
        alu_srcA        = 2'b10;
        alu_srcB        = 2'b01;
        mem_write       = 1'b1;
        mem_en          = 1'b1;
        result_src      = 2'b00;
        branch          = 1'b0;
        alu_op          = 2'b00;
        jump            = 1'b0;
        case(funct3)
            3'b100 : mem_write_mask  = 4'b1111;
            3'b010 : mem_write_mask  = 4'b0011;
            3'b001 : mem_write_mask  = 4'b0001;
            default: mem_write_mask  = 4'b0000;
        endcase
    end
    7'b01100_11: begin    //R-type
        reg_write       = 1'b1;
        imm_src         = 3'b000;
        alu_srcA        = 2'b10;
        alu_srcB        = 2'b00;
        mem_write       = 1'b0;
        mem_en          = 1'b0;
        mem_write_mask  = 4'b0000;
        result_src      = 2'b00;
        branch          = 1'b0;
        alu_op          = 2'b10;
        jump            = 1'b0;
    end
    7'b11000_11: begin    //beq
        reg_write       = 1'b0;
        imm_src         = 3'b010;
        alu_srcA        = 2'b10;
        alu_srcB        = 2'b00;
        mem_write       = 1'b0;
        mem_en          = 1'b0;
        mem_write_mask  = 4'b0000;
        result_src      = 2'b00;
        branch          = 1'b1;
        alu_op          = 2'b01;    //judge
        jump            = 1'b0;
    end
    7'b00100_11: begin    //I-type
        reg_write       = 1'b1;
        imm_src         = 3'b000;
        alu_srcA        = 2'b10;
        alu_srcB        = 2'b01;
        mem_write       = 1'b0;
        mem_en          = 1'b0;
        mem_write_mask  = 4'b0000;
        result_src      = 2'b00;
        branch          = 1'b0;
        alu_op          = 2'b10;
        jump            = 1'b0;
    end
    7'b11011_11: begin    //jal
        reg_write       = 1'b1;
        imm_src         = 3'b011;
        alu_srcA        = 2'b00;
        alu_srcB        = 2'b01;
        mem_write       = 1'b0;
        mem_en          = 1'b0;
        mem_write_mask  = 4'b0000;
        result_src      = 2'b10;
        branch          = 1'b0;
        alu_op          = 2'b00;
        jump            = 1'b1;
    end
    7'b11001_11: begin    //jalr
        reg_write       = 1'b1;
        imm_src         = 3'b000;
        alu_srcA        = 2'b10;
        alu_srcB        = 2'b01;
        mem_write       = 1'b0;
        mem_en          = 1'b0;
        mem_write_mask  = 4'b0000;
        result_src      = 2'b10;
        branch          = 1'b0;
        alu_op          = 2'b00;
        jump            = 1'b1;
    end
    7'b01101_11: begin    //lui U-type
        reg_write       = 1'b1;
        imm_src         = 3'b100;
        alu_srcA        = 2'b00;
        alu_srcB        = 2'b00;
        mem_write       = 1'b0;
        mem_en          = 1'b0;
        mem_write_mask  = 4'b0000;
        result_src      = 2'b11;
        branch          = 1'b0;
        alu_op          = 2'b00;
        jump            = 1'b0;
    end
    7'b00101_11: begin    //auipc U-type
        reg_write       = 1'b1;
        imm_src         = 3'b100;
        alu_srcA        = 2'b00;
        alu_srcB        = 2'b01;
        mem_write       = 1'b0;
        mem_en          = 1'b0;
        mem_write_mask  = 4'b0000;
        result_src      = 2'b00;
        branch          = 1'b0;
        alu_op          = 2'b00;
        jump            = 1'b0;
    end
    default: begin
        reg_write       = 1'b0;
        imm_src         = 3'b000;
        alu_srcA        = 2'b00;
        alu_srcB        = 2'b00;
        mem_write       = 1'b0;
        mem_en          = 1'b0;
        mem_write_mask  = 4'b0000;
        result_src      = 2'b00;
        branch          = 1'b0;
        alu_op          = 2'b00;
        jump            = 1'b0;
    end
    endcase
end

endmodule
